#ifndef AUDIO_STREAM_TTS_H
#define AUDIO_STREAM_TTS_H

#include <string>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <portaudio.h>
#include <functional>
#include "sherpa-onnx/c-api/c-api.h"

// #include <webrtc_audio_processing/webrtc/modules/audio_processing/include/audio_processing.h>

#include <samplerate.h> // libsamplerate 头文件

// TtsEngine 类：负责加载 TTS 模型并生成音频数据
// TtsEngine 类只有一个重要方法：generate，将文本转为音频数据，这个函数耗费时间会很长
class TtsEngine {
public:
    // 构造函数：初始化 TTS 模型
    TtsEngine();

    // 析构函数：释放 TTS 模型资源
    ~TtsEngine();

    // 生成音频数据：将文本转换为音频数据
    std::vector<float> generate(const std::string &text, int sid = 0, float speed = 1.0f);

private:
    const SherpaOnnxOfflineTts *tts_;  // TTS 模型句柄

    // std::unique_ptr<webrtc::AudioProcessing> audio_processing_ptr;
};




// AudioPlayer 类：负责实时音频播放
// 类对外的重要接口是 pushAudio，负责将浮点类型的音频信号复制到 audio_buffer_ 缓冲区进行播放
// 在构造 AudioPlayer 完毕之后，只需要不断地向 audio_buffer_ 缓冲区复制内容就行了
// 如果不需要进行播放的话，使用 stop 函数来停止播放
class AudioPlayer {
public:
    // 构造函数：初始化音频播放器
    AudioPlayer(int sample_rate = 22050, int frames_per_buffer = 512);

    // 析构函数：释放音频播放器资源
    ~AudioPlayer();

    // 启动音频播放器
    void start();

    // 停止音频播放器
    void stop();

    // 列出 all audio player device
    void printAllDevices(void);

    // 将音频数据推送到播放缓冲区
    void pushAudio(const std::vector<float> &samples);

    // 检查音频是否正在播放
    bool isPlaying() const;

    // 检查 portAudio 的内部缓冲区是否存在数据
    bool audio_buffer_empty(void) {
        if (stream_) {
            return Pa_GetStreamWriteAvailable(stream_);
        }
        return false;
    }

    // buffer_transitionToEmpty_callback 是音频缓冲区从上一次有数据变为这次无数据的回调
    void setBufferTransitionToEmptyCallback(std::function<void(void)> func) {
        buffer_transitionToEmpty_callback = func;
    }

    void clearAudioBuffer(void) {

        // 保护 audio_buffer_ 变量
        std::unique_lock<std::mutex> lock(audio_mutex_);

        // 清空 audio_buffer_ 变量
        std::queue<float> empty;
        std::swap(audio_buffer_, empty);  // 交换后，audio_buffer_ 变为空
    }


    void fillSilence(void) {
        for (size_t i = 0; i < frames_per_buffer_; ++i) {
            audio_buffer_.push(0.0f);
        }
    }

    void manualRunTransitionToEmptyCB() {
        if (buffer_transitionToEmpty_callback) {
            buffer_transitionToEmpty_callback();
        }
    }

    void setMute(bool mute) {
        is_mute = mute;
    }

    bool mute(void) {
        return is_mute;
    }
    

private:
    // PortAudio 回调函数：用于填充音频数据，真正调用的是 audioCallback
    static int paCallback(const void *inputBuffer, void *outputBuffer,
                          unsigned long framesPerBuffer,
                          const PaStreamCallbackTimeInfo *timeInfo,
                          const PaStreamCallbackFlags statusFlags,
                          void *userData);

    // 音频回调函数：将 audio_buffer_ 缓冲区复制到真正的 audio 缓冲区来进行播放
    int audioCallback(void *outputBuffer, unsigned long framesPerBuffer);

    int sample_rate_;                  // 音频采样率
    int frames_per_buffer_;            // 每个缓冲区的帧数
    PaStream *stream_;                 // PortAudio 音频流
    std::atomic<bool> is_playing_;     // 播放状态标志
    std::queue<float> audio_buffer_;   // 音频数据缓冲区
    mutable std::mutex audio_mutex_;   // 互斥锁，保护 audio_buffer_

    std::function<void(void)> buffer_transitionToEmpty_callback;

    // 记录上一次音频缓冲区是否为空
    bool lastAudioBufferEmpty = true;
    // 记录这次音频缓冲区是否为空
    bool curAudioBufferEmpty = true;


    int maxDevchannel = 1;

    bool is_mute = false;

    // sample rate transform
    SRC_STATE* src_state;
};

#endif // AUDIO_STREAM_TTS_H
